﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Collections.Specialized;
using System.ServiceModel.Channels;
using System.Net;
using System.Text.RegularExpressions;
using System.Web;
using suanpan.API.Components.Core;

namespace suanpan.API.Components.OAuth
{
    public class OAuthContext
    {
        #region Properties

        public NameValueCollection Headers { get; set; }
        public NameValueCollection QueryParameters { get; set; }
        public NameValueCollection Cookies { get; set; }
        public NameValueCollection FormEncodedParameters { get; set; }
        public string RawEntityBody { get; set; }
        public Uri RequestUri { get; set; }
        public string RequestMethod { get; set; }
        public string ConsumerKey { get; set; }
        public string AuthorizationHeader 
        {
            get 
            {
                if (this.Headers.AllKeys.Contains<string>(Parameters.OAuth_Authorization_Header))
                    return this.Headers[Parameters.OAuth_Authorization_Header];
                else
                    return null;
            }
        }

        #endregion

        #region CTor

        public OAuthContext(Message message)
        {
            this.Headers = new NameValueCollection();
            this.QueryParameters = new NameValueCollection();
            this.Cookies = new NameValueCollection();
            BuildContext(message);
        }

        #endregion

        #region Methods

        //public static OAuthContext Current
        //{
        //    get { return OperationContext.Current.InstanceContext.Extensions.Find<MySpaceContextExtension>().Context; }
        //}

        private void BuildContext(Message message)
        {
            HttpRequestMessageProperty requestProperty = message.Properties[HttpRequestMessageProperty.Name] as HttpRequestMessageProperty;

            if (requestProperty == null)
                return;

            PopulateHeaders(requestProperty);
            PopulateCookies(requestProperty);
            PopulateQueryParameters(requestProperty);
            PopulateRequestInfo(requestProperty, message);
            PopulateFormEncodedParameters(requestProperty, message);
        }
        /// <summary>
        /// Populate headers into Context
        /// </summary>
        /// <param name="requestProperty"></param>
        private void PopulateHeaders(HttpRequestMessageProperty requestProperty)
        {
            foreach (string header in requestProperty.Headers)
            {
                this.Headers.Add(header, requestProperty.Headers[header]);
            }
        }

        /// <summary>
        /// Populate cookies
        /// </summary>
        /// <param name="requestProperty"></param>
        private void PopulateCookies(HttpRequestMessageProperty requestProperty)
        {

            string cookieHeader = requestProperty.Headers[HttpRequestHeader.Cookie];
            if (!string.IsNullOrEmpty(cookieHeader))
            {
                string[] cookies = cookieHeader.Split(';');
                foreach (string cookie in cookies)
                {
                    //Remove the trailing and Leading white spaces
                    string strCookie = cookie.Trim();

                    Regex reg = new Regex(@"^(\S*)=(\S*)$");
                    if (reg.IsMatch(strCookie))
                    {
                        Match match = reg.Match(strCookie);
                        if (match.Groups.Count > 2)
                        {
                            this.Cookies.Add(match.Groups[1].Value,
                                HttpUtility.UrlDecode(match.Groups[2].Value).Replace(' ', '+')); //HACK: find out why + is coming in as " "
                        }
                    }
                }
            }
        }

        /// <summary>
        /// Populate querystring parameters
        /// </summary>
        /// <param name="requestProperty"></param>
        private void PopulateQueryParameters(HttpRequestMessageProperty requestProperty)
        {
            string query = requestProperty.QueryString;
            this.QueryParameters = HttpUtility.ParseQueryString(requestProperty.QueryString);
        }

        /// <summary>
        /// Populate other request information into the context
        /// </summary>
        /// <param name="requestProperty"></param>
        private void PopulateRequestInfo(HttpRequestMessageProperty requestProperty, Message message)
        {
            this.RequestMethod = requestProperty.Method;
            Uri host = new Uri(string.Format("http://{0}", this.Headers[HttpRequestHeader.Host.ToString()]));

            if (this.Headers.AllKeys.Contains<string>("X-REWRITE-URL"))
            {
                this.RequestUri = new Uri(host, this.Headers["X-REWRITE-URL"]);
            }
            else
            {
                this.RequestUri = new Uri(host, message.Properties.Via.AbsolutePath);
            }
        }


        private void PopulateFormEncodedParameters(HttpRequestMessageProperty requestProperty, Message message)
        {
            if (requestProperty.Method == "POST" || requestProperty.Method == "PUT")
            {
                string contentType = this.Headers.AllKeys.Contains<string>("Content-Type") ? this.Headers["Content-Type"] : string.Empty;
                if (contentType == "application/x-www-form-urlencoded")
                {
                    string str = HttpStreamReader.ReadRawEntityBody(message);
                    this.RawEntityBody = str;
                    this.FormEncodedParameters = HttpUtility.ParseQueryString(str);
                }
            }
        }


        #endregion
    }
}
